package org.xc.uvc_camera.encoder;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;

import com.sinaapp.bashell.VoAACEncoder;

import org.xc.uvc_camera.FileUtil;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by idea on 2017/12/11.
 */

public class AacEncoder {

    String TAG="AacEncoder";

    private static AacEncoder instance;
    public static AacEncoder getInstance(){
        if(instance==null){
            synchronized (AacEncoder.class){
                if(instance==null){
                    instance = new AacEncoder();
                }
            }
        }
        return instance;
    }
    private AacEncoder(){
        //计算最小缓冲区
        bufferSize = AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig, audioFormat);
        bufferSize= bufferSize > 320 ? 320 : bufferSize;

        //pcm采集
        audioRecord = new AudioRecord(MediaRecorder.AudioSource.CAMCORDER,sampleRateInHz,channelConfig, audioFormat, bufferSize);//创建AudioRecorder对象
        //aac编码
        voAACEncoder = new VoAACEncoder();
        voAACEncoder.Init(sampleRateInHz,32000,(short) 1,(short)1);
    }

    //true表示正在录音
    public boolean isRecord = false;
    //reset
    public boolean isReset = false;


    //pcm采集
    private AudioRecord audioRecord;
    //pcm编码为aac
    private VoAACEncoder voAACEncoder;

    //采集配置
    private int bufferSize;//最小缓冲区大小
    private int sampleRateInHz = 44100;//采样率
    private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_DEFAULT; //单声道
    private int audioFormat = AudioFormat.ENCODING_PCM_16BIT; //量化位数

    private FileOutputStream fos;
    private String currFileName;

    /**
     * 开始音频采集
     * @param callback
     */
    public void startRecording(String fileName,IOnEncoderCallback callback) {
        this.isReset = true;
        if (!isRecord) {
            isRecord = true;
            new Thread(() -> {
                try {
                    byte[] buffer = new byte[bufferSize];
                    //开始录音
                    audioRecord.startRecording();
                    //循环取录音数据
                    while (isRecord) {
                        //是否重置文件
                        if (isReset) {
                            isReset = false;
                            closeFile();

                            try {
                                currFileName = fileName;
                                onEncoderCallback = callback;
                                fos = new FileOutputStream(FileUtil.createFile(currFileName + ".aac"));
                            } catch (FileNotFoundException e) {
                                e.printStackTrace();
                            }
                        }

                        //视频准备完毕，写入数据
                        if (H264Encoder.getInstance().isRecord) {
                            int bufferReadResult = audioRecord.read(buffer,0,bufferSize);
                            if (bufferReadResult > 0) {
                                //aac数据
                                byte[] data = voAACEncoder.Enc(buffer);
                                fos.write(data);
                            }
                        }
                    }

                    closeFile();
                    voAACEncoder.Uninit();
                    audioRecord.stop();
                    audioRecord.release();
                } catch (Throwable t) {
                    Log.e(TAG, "Recording Failed");
                }
            }).start();
        }
    }

    private void closeFile() {
        if (fos != null) {
            try {
                fos.flush();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (onEncoderCallback != null) {
                onEncoderCallback.over(currFileName);
            }
        }
    }

    /**
     * 停止音频采集
     */
    public void close() {
        isRecord = false;
    }

    public interface IOnEncoderCallback{

        void over(String fileName);
    }

    private IOnEncoderCallback onEncoderCallback;

}